// ==UserScript==
// @name         cursorTotal
// @namespace    https://gitee.com/blb19900404/tampermonkey/tree/master
// @version      1.0.3
// @description  获取curosr的统计Suggested Lines与Accepted Lines
// @author       zf
// @match        https://cursor.com/dashboard*
// @match        https://cursor.com/*/dashboard*
// @icon         
// @updateURL    https://gitee.com/blb19900404/tampermonkey/raw/master/script/cursorTotal.js
// @downloadURL  https://gitee.com/blb19900404/tampermonkey/raw/master/script/cursorTotal.js
// @grant        none
// ==/UserScript==

(function () {
  "use strict";

  /**
   * @typedef {Object} UsageCount 用户次数
   * @property {string} name 名称
   * @property {number} count 数量
   */

  /**
   * @typedef {Object} AnalyticsRecord 统计相关内容
   * @property {string} date 日期（时间戳）
   * @property {number} activeUsers 活跃用户数
   * @property {number} linesAdded 新增行数
   * @property {number} linesDeleted 删除行数
   * @property {number} acceptedLinesAdded 接受行数
   * @property {number} acceptedLinesDeleted 接受删除行数
   * @property {number} totalApplies 总申请数
   * @property {number} totalAccepts 总接受数
   * @property {number} totalTabsShown 总标签显示数
   * @property {number} totalTabsAccepted 总标签接受数
   * @property {number} agentRequests 代理请求数
   * @property {number} cmdkUsages CMDK使用次数
   * @property {number} subscriptionIncludedReqs 订阅包含请求数
   * @property {UsageCount[]} modelUsage 模型使用次数
   * @property {UsageCount[]} extensionUsage 扩展使用次数
   * @property {UsageCount[]} tabExtensionUsage 标签扩展使用次数
   * @property {UsageCount[]} clientVersionUsage 客户端版本使用次数
   */

  let oldFetch = fetch;
  function hookFetch() {
    const url = arguments[0];
    if (typeof url === "string" && url?.includes("get-user-analytics")) {
      // fetch需要返回一个promise，所以这里我们new一个Promise返回，
      // 然后自行处理fetch的逻辑后resolve出去
      return new Promise((resolve, reject) => {
        // 这里我们使用fetch的原函数，
        // 通过apply更改了this指针至自身，并且传入了参数
        // 我们劫持函数的时候，
        // 由劫持函数调用原函数的过程中一定要使用call/apply进行修改this指针，
        // 以符合原来的调用过程。
        // 在then中则是我们处理response的过程
        oldFetch.apply(this, arguments).then(async (response) => {
          // 首先保存了原json的引用
          const oldJson = response.json;

          response.json = function () {
            // 由于json返回的是一个promise对象，
            // 所以我们这里也需要返回一个promise
            return new Promise((resolve, reject) => {
              // 在promise内依对其原json函数进行调用，
              // 并修改了this指向以及参数
              // 最后对其结果进行一定的修改，
              // 然后通过resolve(result)进行返回
              oldJson.apply(this, arguments).then((result) => {
                const res = result;
                /**
                 * @type {AnalyticsRecord[]} DailyMetrics 统计相关内容
                 */
                const dailyMetrics = res.dailyMetrics;
                const SuggestedLines = dailyMetrics.reduce((acc, item) => {
                  return (
                    acc + (item.linesDeleted || 0) + (item.linesAdded || 0)
                  );
                }, 0);
                const AcceptedLines = dailyMetrics.reduce((acc, item) => {
                  return (
                    acc +
                    (item.acceptedLinesDeleted || 0) +
                    (item.acceptedLinesAdded || 0)
                  );
                }, 0);
                const dom = document.querySelector(
                  ".border-brand-neutrals-100 .dashboard-base.mb-4.font-medium"
                );
                dom.innerHTML = `
                          Your Analytics：
                          <div>
                            <div>Suggested Lines: ${SuggestedLines}</div>
                            <div>Accepted Lines: ${AcceptedLines}</div>
                          </div>
                        `;
                resolve(result);
              });
            });
          };
          resolve(response);
        });
      });
    }

    return oldFetch.apply(this, arguments);
  }

  window.fetch = hookFetch;
})();
